#include "interpolation.h"
#include <cstdlib>
#include <filesystem>

using namespace std;

double f1(double x) { return 1.0 / (1 + x * x); }
double f2(double x) { return 1.0 / (1 + 25 * x * x); }

void output_exactfun(double (*f)(double), const char *filename, double left, double right, double grid = 0.01)
{
    std::ofstream outputFile(filename); // 打开输出文件

    std::streambuf *originalCout = std::cout.rdbuf(); // 保存原始的 std::cout 缓冲区

    std::cout.rdbuf(outputFile.rdbuf()); // 重定向 std::cout 到输出文件

    for (double x = left; x <= right; x += grid)
    {
        double y = f(x);
        std::cout << x << " " << y << std::endl;
    }

    std::cout.rdbuf(originalCout); // 恢复原始的 std::cout 缓冲区

    outputFile.close(); // 关闭文件
}

void problemB()
{
    vector<double> xvec(10);
    const char *filename[4] = {"txtfile/Bf1.txt", "txtfile/Bf2.txt", "txtfile/Bf3.txt", "txtfile/Bf4.txt"};
    for (int j = 1; j <= 4; j++)
    {
        int n = 2 * j;
        for (int i = 0; i <= n; i++)
        {
            xvec[i] = -5.0 + 10.0 * i / n;
        }

        NewtonInterpolation t{xvec, n, f1};
        t.output_file(filename[j - 1], -5.0, 5.0);
    }
    output_exactfun(f1, "txtfile/Bf0.txt", -5.0, 5.0);
    cout << endl
         << "problem B:" << endl
         << "picture is drawn by python" << endl;
}

void problemC()
{
    const char *filename[4] = {"txtfile/Cf1.txt", "txtfile/Cf2.txt", "txtfile/Cf3.txt", "txtfile/Cf4.txt"};
    for (int j = 1; j <= 4; j++)
    {
        int n = 5 * j;

        ChebyshevInterpolation t{n, f2};
        t.output_file(filename[j - 1], -1.0, 1.0);
    }
    output_exactfun(f2, "txtfile/Cf0.txt", -1.0, 1.0);
    cout << endl
         << "problem C:" << endl
         << "picture is drawn by python" << endl;
}

void problemD()
{

    vector<double> time{0, 3, 5, 8, 13};
    vector<int> m{1, 1, 1, 1, 1};
    vector<vector<double>> d_v{vector<double>{0, 75}, vector<double>{225, 77},
                               vector<double>{383, 80}, vector<double>{623, 74}, vector<double>{993, 72}};

    HermiteInterpolation t{time, m, d_v};

    cout << endl
         << "problem D: " << endl
         << "the position: " << t.evaluate(10) << " feet" << endl
         << "the speed: " << t.diff(10) << " feet per second" << endl
         << "according to the picture, the car exceeded the speed limit of 81 feet per second" << endl;

    std::ofstream outputFile("txtfile/Df.txt");       // 打开输出文件
    std::streambuf *originalCout = std::cout.rdbuf(); // 保存原始的 std::cout 缓冲区
    std::cout.rdbuf(outputFile.rdbuf());              // 重定向 std::cout 到输出文件

    for (double x = 0.0; x <= 13; x += 0.01)
    {
        cout << x << " " << t.diff(x) << endl;
    }

    std::cout.rdbuf(originalCout); // 恢复原始的 std::cout 缓冲区
    outputFile.close();            // 关闭文件

    // for (double x = 0.0; x <= 13; x += 0.1)
    // {
    //     if (t.diff(x) > 81)
    //     {
    //         cout << "the car exceeded the speed limit of 81 feet per second" << endl;
    //         return;
    //     }
    // }
    // cout << "the car didn't exceed the speed limit of 81 feet per second" << endl;
    // return;
}

void problemE()
{
    int n = 6;
    vector<double> day{0, 6, 10, 13, 17, 20, 28};
    vector<double> sp1{6.67, 17.3, 42.7, 37.3, 30.1, 29.3, 28.7};
    vector<double> sp2{6.67, 16.1, 18.9, 15.0, 10.6, 9.44, 8.89};

    NewtonInterpolation t1{day, n, sp1}, t2{day, n, sp2};
    t1.output_file("txtfile/Ef1.txt", 0.0, 43.0);
    t2.output_file("txtfile/Ef2.txt", 0.0, 43.0);

    cout << endl
         << "problem E:" << endl
         << "picture is drawn by python" << endl
         << "after 15 day" << endl
         << "the weight of sp1: " << t1.evaluate(43) << endl
         << "the weight of sp2: " << t2.evaluate(43) << endl
         << "according to the picture, average weight of sp2 being minus on the second day is caused by Runge phenomenon. "
         << "sp1 still alive after 15 days.obviously, sp2 will not die." << endl;
}

int main()
{
    // 创建文件夹txtfile
    std::string folder_name = "txtfile"; // 文件夹名称
    if (!std::filesystem::exists(folder_name))
    {
        if (std::filesystem::create_directory(folder_name))
        {
            std::cout << "文件夹创建成功" << std::endl;
        }
        else
        {
            std::cout << "无法创建文件夹" << std::endl;
        }
    }
    // 运行题目对应程序
    problemB();
    problemC();
    problemD();
    problemE();

    int exitCode = std::system("python function_plot.py");
    if (exitCode == 0)
    {
        std::cout << "Python script executed successfully." << std::endl;
    }
    else
    {
        std::cout << "Failed to execute Python script." << std::endl;
    }

    return 0;
}